package com.freemalll.merchant.utils.common;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.freemalll.merchant.annotation.common.QueryCondition;
import com.freemalll.merchant.annotation.common.QueryConditions;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author luohui
 * Query查询类
 */
@Slf4j
public class QueryUtil {

    /**
     * 获取查询的query
     * @param bean
     * @return
     * @param <T>
     */
    public static <T> QueryWrapper getQueryWrapper(T bean){
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        if (bean == null) {
            return queryWrapper;
        }
        try {
            List<Object[]> fields = getFields(bean.getClass());
            for (Object[] os : fields){
                Field field = (Field) os[0];
                QueryCondition q = (QueryCondition) os[1];
                Object val = getTargetValue(bean, field, q);
                if(val == null) {continue;}
                String filedColumn = StringUtils.isBlank(q.column()) ? StrUtil.toUnderlineCase(field.getName()) :q.column();
                switch (q.func()) {
                    case GE: // 大于等于
                        queryWrapper.ge(filedColumn, val);
                        break;
                    case GT: //大于
                        queryWrapper.gt(filedColumn, val);
                        break;
                    case LE: //小于等于
                        queryWrapper.le(filedColumn, val);
                        break;
                    case LT: //小于
                        queryWrapper.lt(filedColumn, val);
                        break;
                    case INNER_LIKE: //中模糊查询
                        queryWrapper.like(filedColumn, val);
                        break;
                    case LEFT_LIKE: //左模糊查询
                        queryWrapper.likeLeft(filedColumn, val);
                        break;
                    case RIGHT_LIKE: //右模糊查询
                        queryWrapper.likeRight(filedColumn, val);
                        break;
                    case IN: //包含
                        if (field.getGenericType().toString().equals("class java.lang.String")) {
                            queryWrapper.in(filedColumn, ((String)val).split(q.separator()));
                        } else if (CollUtil.isNotEmpty((Collection) val)) {
                            queryWrapper.in(filedColumn, (Collection) val);
                        }
                        break; //不等于
                    case NE:
                        queryWrapper.ne(filedColumn, val);
                        break;
                    case NOT_NULL: //不为空
                        queryWrapper.isNotNull(filedColumn);
                        break;
                    case BETWEEN:  //between
                        List between = new ArrayList<>((List) val);
                        queryWrapper.between(filedColumn, between.get(0), between.get(1));
                        break;
                    case UNIX_TIMESTAMP: //查询时间
                        List UNIX_TIMESTAMP = new ArrayList<>((List) val);
                        if (!UNIX_TIMESTAMP.isEmpty()) {
                            SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            Date time1 = fm.parse(UNIX_TIMESTAMP.get(0).toString());
                            Date time2 = fm.parse(UNIX_TIMESTAMP.get(1).toString());
                            queryWrapper.between(filedColumn, time1, time2);
                        }
                        break;
                    default: //默认等于
                        queryWrapper.eq(filedColumn,val);
                        break;
                }
            }
        } catch (Exception e) {
            log.error("设置查询条件失败{}", e);
        }
        return queryWrapper;
    }

    /**
     * 获取bean值
     * @param vo
     * @param field
     * @return
     * @throws Exception
     */
    private static Object getObjectValue(Object vo, Field field) throws Exception {
        Object o = field.get(vo);
        if(o == null) {return null;}
        if (field.getGenericType().toString().equals("class java.lang.String")) {
            String val = (String) o;
            if (StringUtils.isBlank(val)) {
                o = null;
            }
        } else
            // 如果类型是Integer
            if (field.getGenericType().toString().equals("class java.lang.int")) {
                int val = Integer.parseInt((String) o);
                if (val == 0) {
                    o = null;
                }
            } else {
                // 如果类型是Double
                if (field.getGenericType().toString().equals("class java.lang.long")) {
                    long val = Long.parseLong((String) o);
                    if (val == 0) {
                        o = null;
                    }
                }
            }
        return o;
    }
    /**
     * 获取bean中的属性值
     *
     * @param vo    实体对象
     * @param field 字段
     * @param query 注解
     * @return 最终的属性值
     * @throws Exception
     */
    private static Object getTargetValue(Object vo, Field field, QueryCondition query) throws Exception {
        Object o = getObjectValue(vo, field);
        if(o == null) {return o;}
        if (StringUtils.isNotEmpty(query.targetAttr())) {
            String target = query.targetAttr();
            if (target.contains(".")) {
                String[] targets = target.split("[.]");
                for (String name : targets) {
                    o = getValue(o, name);
                }
            } else {
                o = getValue(o, target);
            }
        }
        return o;
    }

    /**
     * 以类的属性的get方法方法形式获取值
     *
     * @param o
     * @param name
     * @return value
     * @throws Exception
     */
    private static Object getValue(Object o, String name) throws Exception {
        if (null != o && StringUtils.isNotEmpty(name)) {
            if(o instanceof Map) {
                Map<String, Object> objectMap = Convert.toMap(String.class, Object.class, o);
                if(objectMap.containsKey(name)) {
                    return objectMap.get(name);
                }
                return null;
            } else {
                Class<?> clazz = o.getClass();
                Field field = clazz.getDeclaredField(name);
                field.setAccessible(true);
                o =  getObjectValue(o, field);
            }
        }
        return o;
    }

    /**
     * 获取字段注解信息
     */
    private static List<Object[]> getFields(Class clazz) {
        List<Object[]> fields = new ArrayList<Object[]>();
        List<Field> tempFields = new ArrayList<>();
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        for (Field field : tempFields) {
            // 单注解
            if (field.isAnnotationPresent(QueryCondition.class)) {
                QueryCondition attr = field.getAnnotation(QueryCondition.class);
                if (attr != null ) {
                    field.setAccessible(true);
                    fields.add(new Object[]{field, attr});
                }
            }

            // 多注解
            if (field.isAnnotationPresent(QueryConditions.class)) {
                QueryConditions attrs = field.getAnnotation(QueryConditions.class);
                QueryCondition[] querys = attrs.value();
                for (QueryCondition attr : querys) {
                    if (attr != null) {
                        field.setAccessible(true);
                        fields.add(new Object[]{field, attr});
                    }
                }
            }
        }
        return fields;
    }


}
